import os, sys, time
import threading, Queue
import fcntl, socket, struct

from ivic.core import Utils
from ivic.core import Logging
from ivic.vprocess.Vprocess import *
from ivic.vprocess.ServerMonitor import *
from ivic.vprocess.Config import vprocess_config

logger = Logging.get_logger('ivic.vprocess.VprocessMonitor')

def urljoin(seqs):
    url = ""
    try:
        for each in seqs:
            if each[0] == '/':
                each = each[1:]
            if each[-1] != '/':
                each = each + "/"
            url = url + each
    except:
        pass
    #url = '/'.join(seqs)
    return url

#****************vprocess server main tracker ********************#
class VprocessTracker(threading.Thread):
    
    def __init__(self, server):
        threading.Thread.__init__(self)
        self.userproc = server.userproc
        self.running = True
    
    def run(self):
        try:
            while self.running:
                try:
                    for user, vprocs in self.userproc.items():
                        for proc in vprocs:
#                            logger.debug(str(proc))
                            try:
                                if proc.state == "running": 
#                                    logger.debug(str(proc))
                                    proc.poll()
                            except Exception, e:
                                logger.error("%s" % e)       
                except Exception, e:
                    logger.error("%s" % e)
                time.sleep(10)
        except Exception, e:
            logger.error("%s" % e)
            
    def stop(self):
        self.running = False
        
#****************vprocess server main reporter ********************#
attr_map = {"uuid":"uuid",
            "state":"state",
            "softname":"app",
            "create_time":"start",
            "end_time":"exit",
            "user_id":"user",
            "vspace_id":"vspace",
            "pid":"pid"}

class VprocessReporter(threading.Thread):
    
    lock = threading.Lock()
    instance = None
    host_ip_addr = None
    @staticmethod
    def Instance(report_url=None):
        if VprocessReporter.instance is None:
            VprocessReporter.lock.acquire()
            if VprocessReporter.instance is None:
                VprocessReporter.instance = VprocessReporter(report_url)
            VprocessReporter.lock.release()
            
        return VprocessReporter.instance
    
    def __init__(self, report_url=None):   
        threading.Thread.__init__(self)
        self.url = report_url
        self.queue = Queue.Queue(0)
        
        self.server_uuid =  vprocess_config.uuid
        
        if self.server_uuid != None:
            self.running = True
        else:
            self.running = False
        
    def putEvent(self, eventType, info):
        try:
            self.queue.put((eventType, info))
        except Exception, e:
            logger.error("[VprocessReporter]: %s" % e) 
    
    def serialize(self, info):
        try:
            message = ""
            if type(info) == dict:
                for key, value in attr_map.items():
                    #if info[value] is not a string, may cause error, because
                    #a non string var may not has method len.
                    if not info.has_key(value): continue
                    if type(info[value]) is str and len(info[value]) <= 0:
                        continue
                    message = message + "VProcess[%s]=%s&" % (key, info[value])
                
                if  VprocessReporter.host_ip_addr is None:
                    try:
                        VprocessReporter.host_ip_addr = Utils.external_address()
                    except Exception, e:
                        logger.error("Get host ip: %s" % e)
                        return ""
                    
                message += "VProcess[server_addr]=" + VprocessReporter.host_ip_addr
                #vprocess server uuid
                message += '&VProcess[vmiuuid]=%s' % self.server_uuid
                #legacy code
                message += '&server=%s' % self.server_uuid
            return message
        except Exception, e:
            logger.error("Serialize: %s" % e)
            return ""
        
    def run(self):
        try:
            while self.running:
                try:
                    eventType, info = self.queue.get()
#                    logger.debug("%s\t%s" % (eventType, repr(info)))
                    message = self.serialize(info)
                    if message == "": continue
                    
                    command = ""
                    url = self.url
                    
                    try:
                        if eventType == "START":
                            command = "curl -X POST -d \"%s\" -H \"Accept: text/xml\" %s" % (message, url)
                        elif eventType in ("STOP","RUNNING"):
                            url = urljoin([url,info['uuid']])
                            command = "curl -X PUT -d \"%s\" -H \"Accept: text/xml\" %s " % (message, url)
                        elif evenType == "KILL":
                            url = urljoin([url,info['uuid']])
                            command = "curl -X DELETE -H \"Accept: text/xml\" %s" % url
                        
                        if len(command) > 0:
                            try:
                                os.system(command)
                            except Exception, e:
                                logger.error("%s" % e)
                        logger.debug(command)            
                    except Exception, e:
                        logger.error("%s" % e)
                        
                except Exception, e:
                    logger.error("Reporter: %s" % e)
        except Exception, e:
            self.running = False
            logger.error("Report: %s" % e)
                
    def stop(self):
        self.running = False 
        
